from dataclasses import dataclass, field
from typing import Dict, List, Optional, Any, Union
from datetime import datetime
import pandas as pd
from pathlib import Path


@dataclass
class TimeRange:
    """时间范围数据结构"""
    start: datetime
    end: datetime
    
    def __str__(self) -> str:
        return f"{self.start} 到 {self.end}"


@dataclass
class LoaderConfig:
    """数据加载器配置对象"""
    base_path: Union[str, Path]  # 数据根目录
    output_dir: Union[str, Path]  # 输出目录
    record_file: str = "record.csv"  # 记录文件名
    sampling_rate: str = "60s"  # 采样率
    cache_enabled: bool = True  # 是否启用缓存
    cache_dir: Optional[Union[str, Path]] = None  # 缓存目录
    workers: int = 1  # 工作线程数
    
    def __post_init__(self):
        # 确保路径为Path对象
        self.base_path = Path(self.base_path)
        self.output_dir = Path(self.output_dir)
        if self.cache_dir:
            self.cache_dir = Path(self.cache_dir)
        else:
            self.cache_dir = self.output_dir / "cache"


@dataclass
class ProcessOptions:
    """数据处理选项"""
    fill_gaps: bool = True  # 是否填充空缺值
    normalize: bool = True  # 是否标准化数据
    smooth: bool = True  # 是否平滑数据
    smooth_method: str = "linear"  # 平滑方法
    smooth_limit: int = 5  # 平滑限制
    
    
@dataclass
class Record:
    """统一的记录数据结构，替代之前的AnomalyRecord"""
    id: str  # 记录ID
    timestamp: int  # 时间戳(秒)
    datetime: datetime  # 日期时间对象
    level: str  # 级别
    reason: str  # 原因
    component: str  # 组件
    source: str = ""  # 数据源
    cmdb_id: Optional[str] = None  # 组件标识
    metric: Optional[str] = None  # 相关指标
    metadata: Dict[str, Any] = field(default_factory=dict)  # 元数据
    
    def get_time_range(self, before_minutes: int = 20, after_minutes: int = 20, delay_minutes: int = 10) -> TimeRange:
        """根据记录时间计算数据窗口"""
        from datetime import timedelta
        observation_time = self.datetime + timedelta(minutes=delay_minutes)
        start_time = observation_time - timedelta(minutes=before_minutes)
        end_time = observation_time + timedelta(minutes=after_minutes)
        return TimeRange(start=start_time, end=end_time)
    
    @classmethod
    def from_series(cls, series: pd.Series, id_prefix: Optional[str] = None) -> 'Record':
        """从Pandas Series创建记录"""
        # 处理不同字段命名
        timestamp = int(series.get('unix_timestamp', series.get('timestamp', 0)))
        dt_obj = series.get('datetime_obj', series.get('anomaly_dt'))
        
        # 确保日期时间对象
        if not isinstance(dt_obj, datetime):
            dt_obj = pd.to_datetime(timestamp, unit='s')
            
        # 构建ID
        component = series.get('component', '')
        record_id = f"{component}_{timestamp}"
        if id_prefix:
            record_id = f"{id_prefix}_{record_id}"
            
        # 元数据
        metadata = {}
        for key, value in series.items():
            if key not in ['unix_timestamp', 'timestamp', 'component', 'level', 'reason', 
                          'datetime_obj', 'anomaly_dt', 'exp_name', 'cmdb_id', 'metric']:
                metadata[key] = value
                
        return cls(
            id=record_id,
            timestamp=timestamp,
            datetime=dt_obj,
            level=series.get('level', 'unknown'),
            reason=series.get('reason', series.get('metric', 'unknown')),
            component=component,
            source=series.get('exp_name', ''),
            cmdb_id=series.get('cmdb_id'),
            metric=series.get('metric'),
            metadata=metadata
        )


@dataclass
class DataResult:
    """处理结果数据结构"""
    record: Record  # 原始记录
    metrics: pd.DataFrame = field(default_factory=lambda: pd.DataFrame())  # 指标数据
    dependencies: pd.DataFrame = field(default_factory=lambda: pd.DataFrame())  # 依赖数据
    logs: pd.DataFrame = field(default_factory=lambda: pd.DataFrame())  # 日志数据
    time_range: Optional[TimeRange] = None  # 数据时间范围
    observation_time: Optional[int] = None  # 观测时间点
    
    def __post_init__(self):
        # 如果未提供观测时间，从记录计算
        if self.observation_time is None:
            from datetime import timedelta
            dt = self.record.datetime + timedelta(minutes=10)  # 默认延迟10分钟
            self.observation_time = int(dt.timestamp())
            
    def to_experiment_data(self):
        """转换为ExperimentData对象（向后兼容）"""
        from ..utils.experiment_data import ExperimentData
        
        experiment_data = ExperimentData(
            anomaly_id=self.record.id,
            anomaly_timestamp=self.record.timestamp,
            anomaly_datetime=self.record.datetime,
            anomaly_level=self.record.level,
            anomaly_reason=self.record.reason,
            anomaly_component=self.record.component,
            observation_time=self.observation_time,
            metrics_df=self.metrics,
            dependencies_df=self.dependencies,
            logs_df=self.logs
        )
        
        # 设置时间窗口
        if self.time_range:
            experiment_data.set_time_window(self.time_range.start, self.time_range.end)
            
        return experiment_data 